﻿using System.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;

namespace Albatross.WPF.Common.PubSub {
	/// <summary>
	/// Message Received Event Handler for the ISubscription&lt;T&gt; interface.
	/// </summary>
	/// <typeparam name="T">The message type</typeparam>
	/// <param name="sender">sender of the message</param>
	/// <param name="msg">the message itself</param>
	public delegate void MsgReceivedEventHandler<T>(object sender, T msg);
	
	/// <summary>
	/// ISubscription interface contains subscription information for a publisher.  It is created by the publisher when the subscriber subscribe to a message topic.
	/// It is a disposable object and should be disposed by the subscriber when no longer needed.
	/// The classes that implements the ISubscription interface are expected to be immutable!
	/// </summary>
	public interface ISubscription : IDisposable {
		void Init(IPublisher publisher, object subscriber, string topic);
		/// <summary>
		/// Message topic
		/// </summary>
		string Topic { get; }
		/// <summary>
		/// Indicate the subscriber object
		/// </summary>
		object Subscriber { get; }
		/// <summary>
		/// The publisher object
		/// </summary>
		IPublisher Publisher { get; }
		/// <summary>
		/// Indicates the type of the message that the subscription is interested in.
		/// </summary>
		Type MsgType { get; }
		/// <summary>
		/// Invoke the subscription
		/// </summary>
		/// <param name="sender">The sender of the message</param>
		/// <param name="msg"></param>
		void Invoke(object sender, object msg);
		/// <summary>
		/// Perform a type check between MsgType and the incoming msg.  
		/// </summary>
		/// <param name="msg"></param>
		/// <returns></returns>
		bool TypeCheck(object msg);
	}

	public interface ISubscription<T> : ISubscription {
		/// <summary>
		/// The MsgReceived event will be invoked when a message is received.  Subscriber can setup additional handlers using the event.
		/// </summary>
		event MsgReceivedEventHandler<T> MsgReceived;
		
		/// <summary>
		/// Used by the ISubscription object to convert the message to the correct type.  Can be overwritten in combination of TypeCheck to create
		/// special cases for certain types of messages.
		/// </summary>
		/// <param name="msg"></param>
		/// <returns></returns>
		T Convert(object msg);
	}
}
